import { Constructor } from "cc";
import { ECSCmp } from "./ECSComp";
import { ECSWorld } from "./ECSWorld";
import { ECSBase } from "./ECSBase";
import { ArrayMap } from "../../struct/ArrayMap";

export abstract class ECSEntity extends ECSBase {
    /**
     * 实体ID
     */
    public readonly id: number;
    /** 
     * 实体所包含的标签
     */
    public readonly tags: Set<string> = new Set();
    /**
     * 所包含的组件
     */
    private _compMap: ArrayMap<Constructor<ECSCmp>, ECSCmp> = new ArrayMap();


    /** 
     * 获取所属世界 
     */
    private _world: ECSWorld | null = null;
    get world(): ECSWorld | null { return this._world; }


    constructor(id: number, world: ECSWorld) {
        super();
        this.id = id
        this._world = world
    }

    /** 
     * 添加标签 
     */
    addTag(tag: string): this {
        if (!this.hasTag(tag)) {
            this.tags.add(tag)
            this._world.onEntityMatch(this)
        }
        return this;
    }
    
    /** 
     * 是否包含标签 
     */
    hasTag(tag: string): boolean {
        return this.tags.has(tag);
    }

    /** 
     * 移除标签 
     */
    removeTag(tag: string) {
        if (this.hasTag(tag)) {
            this.tags.delete(tag);
            this._world.onEntityMatch(this)
        }
        return this;
    }

    /**
     * 添加组件
     * @param type 
     * @param args 
     * @returns 
     */
    addComponent<T extends ECSCmp>(type: Constructor<T>, ...args: any[]): T {
        if (this.hasComponent(type)) {
            return this.getComponent(type);
        }
        const comp = new type(this);
        comp.onInit(...args);
        this._compMap.set(type, comp);
        this._world.onEntityMatch(this);
        return comp;
    }

    /**
     * 销毁组件
     * @param type 
     * @returns 
     */
    destroyComponent<T extends ECSCmp>(type: Constructor<T>) {
        if (this.hasComponent(type)) {
            const comp = this.getComponent(type)
            comp._ecsDestroy();
            this._compMap.delete(type);
            this._world.onEntityMatch(this);
        }
    }

    /**
     * 销毁所有组件
     */
    destroyAllComponent() {
        const keys = [...this._compMap.keys]
        keys.forEach(key => this.destroyComponent(key));
    }

    /**
     * 获取组件
     * @param type 
     * @returns 
     */
    getComponent<T extends ECSCmp>(type: Constructor<T>): T | null {
        return this._compMap.get(type) as T
    }

    /**
     * 判断组件是否存在
     * @param type 
     * @returns 
     */
    hasComponent<T extends ECSCmp>(type: Constructor<T>): boolean {
        return this._compMap.has(type);
    }

    /**************************内部使用*********************** */
    _ecsEnable(): void {
        this._compMap.forEach(comp => comp.enable = true);
        this.onEnable()
    }

    _ecsDisable(): void {
        this._compMap.forEach(comp => comp.enable = false);
        this.onDisable()
    }

    _ecsUpdate(dt: number): void {
        if (this.enable) {
            this._compMap.forEach(comp => comp._ecsUpdate(dt));
            this.onUpdate(dt);
        }
    }

    _ecsDestroy(): void {
        this.onDestroy();
        this.destroyAllComponent()
        this.tags.clear();
        this._world = null
    }
    /**************************内部使用*********************** */
}